package sdcncsi.ict.counter;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import sdcncsi.ict.counter.CounterService.CounterApp;

public class CounterDBThread implements Runnable{
	//日志记录项
	private static final Log logger = LogFactory.getLog(CounterDBThread.class);
	private static int write_db_times = 0;
	/**
	 * 线程主函数
	 */
	public void run() {
		//写数据库循环
		while(true){
			
			//exe job
			try{
				execute();
			}catch (Exception e) {
				// TODO: handle exception
			}
			
			try {//写数据库休息间隔
				Thread.sleep(CounterService.WRITEDB_INTERVAL);
			} catch (InterruptedException e) {
			}
		}
	}
	
	//job main
	public void execute(){
		//获得临时缓存Map
		LinkedHashMap counterTempCache = CounterCache.tempRecordMap;
		
		//建立收集counterTempCache<键>的list，防止iterator迭代异常
		CounterCache.tempRecordMutex = true;//临时缓存锁，锁住是不允许项临时缓存添加元素
		ArrayList<String> tempCacheKeyList = new ArrayList<String>(counterTempCache.size());
		Iterator tmpCacheItr = counterTempCache.keySet().iterator();
		while(tmpCacheItr.hasNext()){
			String visitKey = (String)tmpCacheItr.next();
			tempCacheKeyList.add(visitKey);//保存<键>到list
		}
		CounterCache.tempRecordMutex = false;//解锁
		if(counterTempCache.size()>0)
			logger.info("计数临时缓存访问记录个数是："+counterTempCache.size());
		
		//遍历缓存中的每个元素
		Iterator<String> keyListItr = tempCacheKeyList.iterator();
		while(keyListItr.hasNext()){
			//得到VisitRecord
			String visitKey = keyListItr.next();
			VisitRecord visitRecord = (VisitRecord)counterTempCache.get(visitKey);
			//获取基本信息
			int appID = visitRecord.getAppID();
			String counterID = visitRecord.getCounterID();
			long timestamp = visitRecord.getTimestamp();
			String now_str = formateDatetime(new Date(timestamp));
			
			try{
				JdbcTemplate jdbcTemplate = DBTool.getJdbcTemplate();
				//1 更新IP信息
				int ip_id = -1;
				String ip = visitRecord.getIp();
				VisitItem ipItem = CounterCache.getGlobalCache(appID, counterID, ip);
				if(ipItem!=null){
					if(ipItem.isNewRecord()){//是新的访问项则写数据库
						String sql = "insert into t_counter_ip(ip,counter_id,app_id,zt_dm,cjsj)" +
								" values('" + ip + "','" + counterID + "'," + appID + ",1,'" + now_str + "')";
						KeyHolder keyHolder = new GeneratedKeyHolder();
						jdbcTemplate.update(new GenKeyPreStatement(sql), keyHolder);write_db_times++;
						ip_id = keyHolder.getKey().intValue();
						ipItem.setGenID(ip_id);
					}else{
						ip_id = ipItem.getID();
					}
				}
				//2 更新引用页信息
				int referer_id = -1;
				String referer = visitRecord.getReferer();
				VisitItem refererItem = CounterCache.getGlobalCache(appID, counterID, referer);
				if(refererItem!=null){
					if(refererItem.isNewRecord()){
						referer = referer.substring(0, 1024>referer.length()?referer.length():1024);
						String sql = "insert into t_counter_referer(url,counter_id,app_id,zt_dm,cjsj)" +
						" values('" + referer + "','" + counterID + "'," + appID + ",1,'" + now_str + "')";
						KeyHolder keyHolder = new GeneratedKeyHolder();
						jdbcTemplate.update(new GenKeyPreStatement(sql), keyHolder);write_db_times++;
						referer_id = keyHolder.getKey().intValue();
						refererItem.setGenID(referer_id);
					}else{
						referer_id = refererItem.getID();
					}
				}
				//3 更新访客UV信息
				int uv_id = -1;
				String uv = visitRecord.getUv();
				VisitItem uvItem = CounterCache.getGlobalCache(appID, counterID, uv);
				if(uvItem!=null){
					if(uvItem.isNewRecord()){
						String sql = "insert into t_counter_uv(uv,counter_id,app_id,zt_dm,cjsj)" +
						" values('" + uv + "','" + counterID + "'," + appID + ",1,'" + now_str + "')";
						KeyHolder keyHolder = new GeneratedKeyHolder();
						jdbcTemplate.update(new GenKeyPreStatement(sql), keyHolder);write_db_times++;
						uv_id = keyHolder.getKey().intValue();
						uvItem.setGenID(uv_id);
					}else{
						uv_id = uvItem.getID();
					}
				}
				//根据应用ID获得计数器应用配置
				CounterApp ca = CounterService.getCounterApp(appID);
				//4 更新操作系统信息
				int os_id = -1;
				if(ca.logOS){
					String os = visitRecord.getOs();
					VisitItem osItem = CounterCache.getGlobalCache(appID, counterID, os);
					if(osItem!=null){
						if(osItem.isNewRecord()){
							String sql = "insert into t_counter_os(os,counter_id,app_id,zt_dm,cjsj)" +
							" values('" + os + "','" + counterID + "'," + appID + ",1,'" + now_str + "')";
							KeyHolder keyHolder = new GeneratedKeyHolder();
							jdbcTemplate.update(new GenKeyPreStatement(sql), keyHolder);write_db_times++;
							os_id = keyHolder.getKey().intValue();
							osItem.setGenID(os_id);
						}else{
							os_id = osItem.getID();
						}
					}
				}
				//5 更新浏览器访问信息
				int browser_id = -1;
				if(ca.logBrowser){
					String browser = visitRecord.getBrowser();
					VisitItem browserItem = CounterCache.getGlobalCache(appID, counterID, browser);
					if(browserItem!=null){
						if(browserItem.isNewRecord()){
							String sql = "insert into t_counter_browser(browser,counter_id,app_id,zt_dm,cjsj)" +
							" values('" + browser + "','" + counterID + "'," + appID + ",1,'" + now_str + "')";
							KeyHolder keyHolder = new GeneratedKeyHolder();
							jdbcTemplate.update(new GenKeyPreStatement(sql), keyHolder);write_db_times++;
							browser_id = keyHolder.getKey().intValue();
							browserItem.setGenID(browser_id);
						}else{
							browser_id = browserItem.getID();
						}
					}
				}
				
				//插入此次访问记录到数据库t_counter_record
				String sql = "insert into t_counter_record(counter_id,app_id," +
						"referer_id,ip_id,uv_id,os_id,browser_id,zt_dm,fwsj)" +
						" values('"+counterID+"',"+appID+","+referer_id+","+ip_id+","+
						uv_id+","+os_id+","+browser_id+",1,'"+now_str+"')";
				jdbcTemplate.update(sql);write_db_times++;
				
				//更新更新appid -> counterid 的计数统计信息
				CounterNumber cn = CounterCache.getCunnterNumber(appID, counterID);
				if(cn!=null){
					if(cn.isNewCounter()){
						sql = "insert into t_counter(id, app_id, pv, ip, uv, ss, zt_dm, cjsj)" +
							" values('"+counterID+"',"+appID+","+cn.getPV()+","+cn.getIP()+"," +
							cn.getUV()+","+cn.getSS()+",1,'"+now_str+"')";
						jdbcTemplate.update(sql);write_db_times++;
						cn.setInserted();
					}
					if(cn.isChanged()){
						sql = "update t_counter" +
							" set pv="+cn.getPV()+",ip="+cn.getIP()+",uv="+cn.getUV()+",ss="+cn.getSS()+
							" where zt_dm=1 and id='"+counterID+"' and app_id="+appID;
						jdbcTemplate.update(sql);write_db_times++;
						cn.setChanged(false);
					}
				}
				
				//最后，从临时缓存清除此条访问记录
				counterTempCache.remove(visitKey);
				//写日志
				//logger.info("写VisitRecord{"+visitRecord+"}到数据库。");
			}catch(DataAccessException e){
				logger.error("写VisitRecord{"+visitRecord+"}到数据库发生异常："+e.toString());
				e.printStackTrace();
			}
		}//遍历一次临时缓存结束
		
		//写日志
		if(write_db_times>0){
			logger.info("遍历一次临时缓存结束(现在计数临时缓存访问记录个数是："+counterTempCache.size()+")。此次写数据库次数："+write_db_times+"。");
			write_db_times = 0;
		}
	}
	//格式化时间 String 日期+时间
	private static String formateDatetime(Date date) {
		java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return format1.format(date);
	}
}
